package cn.virens.common.utils;

import java.util.Arrays;
import java.util.Spliterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * 流工具
 *
 * @author virens
 */
public class StreamUtil {
    /**
     * 生成空流
     *
     * @param <T> 类型
     * @return 流
     */
    public static <T> Stream<T> empty() {
        return Stream.empty();
    }

    /**
     * 根据数组生成流
     *
     * @param <T>    类型
     * @param values 数组
     * @return 流
     */
    @SafeVarargs
    public static <T> Stream<T> stream(T... values) {
        return stream(values != null ? Arrays.spliterator(values) : null);
    }

    /**
     * 根据迭代器生成流
     *
     * @param <T>      类型
     * @param iterable 迭代器
     * @return 流
     */
    public static <T> Stream<T> stream(Iterable<T> iterable) {
        return stream(iterable != null ? iterable.spliterator() : null);
    }

    /**
     * 根据可分割迭代器生成流(并行流)
     *
     * @param <T>         类型
     * @param spliterator 可分割迭代器
     * @return 流
     */
    public static <T> Stream<T> stream(Spliterator<T> spliterator) {
        return spliterator != null ? StreamSupport.stream(spliterator, false) : empty();
    }

    /**
     * 根据数组生成流(并行流)
     *
     * @param <T>    类型
     * @param values 数组
     * @return 流
     */
    @SafeVarargs
    public static <T> Stream<T> parallelStream(T... values) {
        return parallelStream(values != null ? Arrays.spliterator(values) : null);
    }

    /**
     * 根据迭代器生成流(并行流)
     *
     * @param <T>      类型
     * @param iterable 迭代器
     * @return 流
     */
    public static <T> Stream<T> parallelStream(Iterable<T> iterable) {
        return parallelStream(iterable != null ? iterable.spliterator() : null);
    }

    /**
     * 根据可分割迭代器生成流(并行流)
     *
     * @param <T>         类型
     * @param spliterator 可分割迭代器
     * @return 流
     */
    public static <T> Stream<T> parallelStream(Spliterator<T> spliterator) {
        return spliterator != null ? StreamSupport.stream(spliterator, true) : empty();
    }
}
